package emulator.shell.GUI.menu;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JTextField;
import javax.swing.JToolBar;
import javax.swing.UIManager;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

import com.jhe.hexed.JHexEditor;

import emulator.GUI.util.Clipboard;
import emulator.assembler.Assembler;
import emulator.hardware.memory.MemoryBlockInterface;
import emulator.shell.GUI.ToolBarWindow;
import emulator.shell.GUI.debugger.CodeInfo;
import emulator.shell.GUI.windows.ManagedWindow;
import emulator.shell.GUI.windows.WindowManager;

@SuppressWarnings("serial")
public class WindowMemory extends ToolBarWindow implements ActionListener {

	private int window_id;
	private WindowManager window_manager;
	private MemoryBlockInterface memory;
	private JTextField textfield_search;
	private JButton button_search;
	private JHexEditor hex_editor;
	private CodeInfo code_info;
	private ResetSearch _searchResultResetter = new ResetSearch();
	private Search _searchHandler = new Search();
	
	public WindowMemory(WindowManager window_manager, int window_id, Assembler assembler, MemoryBlockInterface memory)
	{
		this.window_manager = window_manager;
		this.window_id = window_id;
		this.memory = memory;
		this.code_info = new CodeInfo(memory.getData(), assembler, CodeInfo.ADDRESS_SPACE);
	}

	@Override
	public void actionPerformed(ActionEvent arg0)
	{
		if (window_manager.isWindowActive(window_id))
			closeWindow();
		else
			openWindow();

	}

	private void openWindow()
	{
		hex_editor = new JHexEditor(memory.getData(), new Clipboard());
		
		ManagedWindow window = window_manager.createWindow(window_id, "Memory");
		window.getContentPane().setLayout(new BorderLayout());
		window.getContentPane().add(createToolBar(), BorderLayout.PAGE_START);
		window.getContentPane().add(hex_editor, BorderLayout.CENTER);
		window.restorePosition();
		window.setVisible(true);
	}

	private JToolBar createToolBar()
	{
		textfield_search = new JTextField();
		textfield_search.addActionListener(_searchHandler);
		textfield_search.getDocument().addDocumentListener(_searchResultResetter);
		button_search = makeNavigationButton("images/search_icon.png", "Search for address or values",  "search", new Search());
		
		textfield_search.setToolTipText(
				"<html><b>Enter search text here.</b><br><br>"+
				"Search for a <i>memory location</i> by <i>address</i> or <i>label</i> (e.g. '$3FC0' or 'init')<br>"+
				"Search for <i>memory contents</i> by using the equal sign (=) followed by<ul>"+
				"<li>a series of byte values (e.g. '=$34 $56')</li>"+
				"<li>an ASCII string (e.g. '=\"load\"')</li>"+
				"</ul></html>");

		JToolBar toolbar = new JToolBar();
		if (memory.getData().length > 65536)
		{
			hex_editor.data.setBufferView(0, 65536);
			String[] memConfigStrings = { "Base memory (64K)",
										  "FE3 Bank 0", "FE3 Bank 1", "FE3 Bank 2", "FE3 Bank 3",
										  "FE3 Bank 4", "FE3 Bank 5", "FE3 Bank 6", "FE3 Bank 7",
										  "FE3 Bank 8", "FE3 Bank 9", "FE3 Bank A", "FE3 Bank B",
										  "FE3 Bank C", "FE3 Bank D", "FE3 Bank E", "FE3 Bank F",
										};
	
			//Create the combo box, select item at index 4.
			//Indices start at 0, so 4 specifies the pig.
			JComboBox memConfigCombo = new JComboBox(memConfigStrings);
			memConfigCombo.setSelectedIndex(0);
			memConfigCombo.addActionListener(new MemoryViewSelector());
			toolbar.add(memConfigCombo);
			toolbar.addSeparator();
		}
		
		toolbar.add(textfield_search);
		toolbar.add(button_search);
		return toolbar;
	}

	private void closeWindow() {
		window_manager.closeWindow(window_id);
	}

	private void signalFailedSearch()
	{
		textfield_search.setBackground(Color.ORANGE);
	}

	private void resetSearch()
	{
		_searchResultResetter.resetVisualState();
		_searchHandler.resetQuery();
		
	}
	
	public class MemoryViewSelector implements ActionListener
	{
		@Override
		public void actionPerformed(ActionEvent e)
		{
			JComboBox cb = (JComboBox)e.getSource();
	        int index = cb.getSelectedIndex();
	        int newOffset = 0;
	        int newSize = 65536;
	        if (index > 0)
	        {
	        	newOffset = (index+1)*32768;
	        	newSize = 32768;
	        }
			hex_editor.data.setBufferView(newOffset, newSize);
			hex_editor.goTo(0);
			resetSearch();
		}

	}

	
	public class ResetSearch implements DocumentListener
	{
		private void resetVisualState()
		{
			Color bk_color = UIManager.getColor("TextField.background");
			textfield_search.setBackground(bk_color);
		}
		
		@Override
		public void changedUpdate(DocumentEvent arg0) {
			resetVisualState();
		}

		@Override
		public void insertUpdate(DocumentEvent arg0) {
			resetVisualState();
		}

		@Override
		public void removeUpdate(DocumentEvent arg0) {
			resetVisualState();
		}
	}

	public class Search implements ActionListener
	{
		private MemoryQuery _query = null;
		private String _searchText = "";

		@Override
		public void actionPerformed(ActionEvent e)
		{
			if (!textfield_search.getText().isEmpty())
			{
				if (!_searchText.equals(textfield_search.getText()) || _query == null)
				{
					_searchText = textfield_search.getText();
					_query = new MemoryQuery(hex_editor.data, _searchText, code_info);
				}
				if (!_query.execute())
					signalFailedSearch();
				else
					hex_editor.goTo(_query.getPosition());
			}
		}

		public void resetQuery()
		{
			_query = null;
		}
	}
}
